package net.israfil.markup.plugin.swing;

import java.awt.Container;
import java.awt.LayoutManager;
import java.util.Map;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.xml.namespace.QName;

import net.israfil.foundation.dynamic.DynamicUtil;
import net.israfil.markup.core.ComponentTracker;
import net.israfil.markup.model.Component;
import net.israfil.markup.model.Layout;
import net.israfil.markup.model.Markup;
import net.israfil.markup.model.View;
import net.israfil.markup.model.swing.SwingComponent;
import net.israfil.markup.plugin.GUI;

public class SwingGUI extends GUI {
			
	private final ComponentTracker<JFrame, JComponent> components;
	private final Markup definition;
	
	public SwingGUI(ComponentTracker<JFrame, JComponent> components, Markup definition) {
		this.components = components;
		this.definition = definition;
	}

	@Override
	protected void process() throws InterruptedException {
		System.out.println("Swing");
		JFrame frame = null;
		Map<String, JFrame> frames = components.getRoots();
		if (frames.containsKey("Main")) frame = frames.get("Main");
		else if (frames.containsKey("Frame0")) frame = frames.get("Frame0");
		else frame = frames.values().iterator().next();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);		
	}
		
	@Override
	protected boolean init() throws InterruptedException {
		View view = definition.getView();
		Integer frameNumber = 0; 
		for (Component c : view.getComponent()) {
			JFrame frame = (JFrame)processComponent(c);
			components.getRoots().put(frameNumber.toString(), frame);
			processComponents(c,frame);			
			frameNumber++;
		}
		return super.init();
	}
	
	private void processComponents(Component markupView, Container awtComponent) {
		for (Component childView : markupView.getComponent()) {
			Container jcomp = processComponent(childView);
			
			if (markupView instanceof SwingComponent) {
				awtComponent.add(jcomp, ((SwingComponent)markupView).getLayoutHint());
			} else awtComponent.add(jcomp);
			processComponents(childView,jcomp);
		}
	}
	private Container processComponent(Component markupView) {
		Container jcomp = getComponentInstance(markupView.getType());
		if (markupView.getX()!=null && markupView.getY()!=null)
			jcomp.setLocation(markupView.getX(),markupView.getY());
		if (markupView.getX()!=null && markupView.getY()!=null)
			jcomp.setSize(markupView.getWidth(), markupView.getHeight());
		if (markupView.getLayout()!= null)
			jcomp.setLayout(processLayout(markupView.getLayout()));
		return jcomp;
	}

	private Container getComponentInstance(String componentName) {
		return getComponentInstance(componentName,null);
	}
	private LayoutManager processLayout(Layout layout) {
		LayoutManager lm = (LayoutManager)DynamicUtil.construct(layout.getType());
		
		return lm;
	}
	private <T> T getComponentInstance(String componentName, Class<T> constraint) {
		T c = (T)DynamicUtil.construct(componentName, new Object[]{});
		if (constraint != null && ! constraint.isAssignableFrom(c.getClass()))
			throw new IllegalArgumentException("Component " + c.getClass().getName() + " does not extend or implement " + constraint.getName());
		else return c;
	}
	
}


